/**
 ******************************************************************************
 * @file	stm32-spi-chip.c
 * @brief	TR700-STM32 调试工具
 *
 *
 *
 * @section Depend
 *	-# spi_mxs.ko
 *	-# spidev.ko
 *	-# libstm32-spi.so
 *
 * 2016-10-19,MenglongWu,MenglongWoo@aliyun.com
 * Copyright (C) 2017 桂林聚联科技有限公司, Inc. All Rights Reserved.
 */


#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>

#include <printl.h>
#include <stdbool.h>

#include "stm32-spi.h"
#include "proginfo.h"
#include "printl.h"

#define PRINTG(fmt, ...) ___cprint(C_GREEN, C_NORMAL, fmt, ##__VA_ARGS__)
#define PRINTR(fmt, ...) ___cprint(C_RED, C_NORMAL, fmt, ##__VA_ARGS__)

#define ARRAY_SIZE(a)    (sizeof(a) / sizeof((a)[0]))

#define STRLEN           (16)

#define DEF_SPI          "/dev/spidev2.0"

static char    *device = DEF_SPI;
static uint32_t speed  = 100000;

struct stm32_spi_dev *dev;

// 是否执行循环测试
// static int is_do_loop = 0;  // 目前未用到

// static char str_freq[STRLEN] = "800mhz";
// static int freq = 800;/*TP_FREQ_800*/;


// 默认APD电压
// static char apd = 0;
// static int is_do_apd = 0;

// 默认关闭红光
// static char red = OTDR_RL_OFF;
static int is_do_red  = 1;
static int is_do_test = 0;

static int is_do_forever = 0;
static int is_do_alive   = 0;

static int is_do_getenv  = 0;
static int is_do_setenv  = 0;
static int is_do_saveenv = 0;
char      *in_env        = NULL;
char      *in_env_val    = NULL;


static int is_do_watch_ls  = 0;
static int is_do_watch_opm = 0;


static char is_do_version = 0;
static int  peek_ms       = 0;  // 0 表示不等待，取值范围0-1000ms


/******************************************************************************
 * 输入提示
 ******************************************************************************/
static void print_usage(const char *prog)
{
    printf("Usage: %s [-DrtpaACw]\n", prog);
    puts(
	    "  -a <alive>  check fpga is alive\n"
	    "  -d <debug>  debug output (-d t -d r -d o)\n"
	    "     -d t   print send\n"
	    "     -d r   print receive\n"
	    "     -d o   print otdr data with simple format\n"
	    "  -D <device> device to use (default /dev/spidev3.0)\n"
	    "  -F <forever> for test SPI bus signal. forevery occupation SPI bus\n"
	    "  -r <red>    red ligth mode \n"
	    "     -r 0/1/s/f  off/on/slop/faster\n"
	    "  -s <speed>  transfer Baud rate (Hz)\n"
	    "  -v <version> check FPGA chip version\n"

    );
    exit(1);
}

static void parse_opts(int argc, char *argv[])
{
    int ret;
    int tval_int;
    while (1) {
	static const struct option lopts[] = {
	    { "alive", 1, 0, 'a' },    // 运放开关级别 --amp 0x0101
	    { "debug", 1, 0, 'd' },    // 打印调试信息  -d t -d r -d o
	    { "device", 1, 0, 'D' },   // SPI设备       -D /dev/spidev3.0
	    { "speed", 1, 0, 's' },    // 传输速率     --speed 10000000
	    { "forever", 1, 0, 'F' },  // 永远循环isalive

	    { "getenv", 1, 0, 'e' },   // 光耦切换     --switch 0-9
	    { "setenv", 1, 0, 'e' },   // 光耦切换     --switch 0-9
	    { "saveenv", 1, 0, 'e' },  // 光耦切换     --switch 0-9

	    { "watch", 1, 0, 'w' },  // 红光开关     --red 0/1/s/f

	    { "amp", 1, 0, 'a' },      // 运放开关级别 --amp 0x0101
	    { "apd", 1, 0, 'A' },      // APD电压级别  --apd 0x0101
	    { "freq", 1, 0, 'f' },     // 采样频率     --freq 800mhz
	    { "add", 1, 0, 'c' },      // 累加次数     --add 1000
	    { "param", 1, 0, 'P' },    // 测试参数     -P 60km/640ns/3min
	    { "laser", 1, 0, 'L' },    // 激光器波长    -L 1310
	    { "panel", 1, 0, 'p' },    // 面板通道      --panel 0
	    { "peek", 1, 0, 'p' },     // 询问完成间隔  --peek 32k
	    { "pt", 1, 0, 'p' },       // 采样点数      --pt 32k
	    { "test", 0, 0, 't' },     // 启动测试
	    { "version", 0, 0, 'v' },  // 获取FPGA版本

	    { NULL, 0, 0, 0 },
	};
	int c;

	c = getopt_long(argc,
	                argv,
	                "d:D:s:S:e:e::r:F::a::a:A:f:P:p:L:C:w:t::v::",
	                lopts,
	                NULL);

	if (c == -1) {
	    break;
	}
	switch (c) {
	case 'd':
	    switch (optarg[0]) {
	    case '1':
		EN_STM32SPI_DBG_LEVEL(BIT_DEF);
		break;
	    case 't':
		EN_STM32SPI_DBG_LEVEL(BIT_TX);
		break;
	    case 'r':
		EN_STM32SPI_DBG_LEVEL(BIT_RX);
		break;
	    case 'b':
		EN_STM32SPI_DBG_LEVEL(BIT_BUSY);
		break;
	    }
	    break;
	case 'D':
	    device = optarg;
	    break;
	case 's':
	    speed = atoi(optarg);
	    break;
	case 'e':
	    if (strcmp("--getenv", argv[optind - 2]) == 0) {
		is_do_getenv = 1;
		in_env       = optarg;
	    }
	    else if (strcmp("--setenv", argv[optind - 2]) == 0) {
		is_do_setenv = 1;

		in_env     = optarg;
		in_env_val = argv[optind];
	    }
	    else if (strcmp("--saveenv", argv[optind - 2]) == 0) {
		is_do_saveenv = 1;
	    }
	    break;
	case 'w':
	    if (strcmp("--watch", argv[optind - 2]) == 0) {
		if (strcmp("ls", optarg) == 0) {
		    is_do_watch_ls = 1;
		}
		else if (strcmp("opm", optarg) == 0) {
		    is_do_watch_opm = 1;
		}
	    }
	    break;
	case 'F':
	    is_do_forever = 1;
	    break;
	case 'v':
	    is_do_version = 1;
	    break;
	case 't':
	    is_do_test = 1;
	    break;

	default:
	    print_usage(argv[0]);
	    break;
	}
    }
}
static void print_configure()
{
}


/******************************************************************************
 * 最终处理
 ******************************************************************************/
void do_forever()
{
    int ret;
    if (is_do_forever == 0) {
	return;
    }
    while (1) {
	// ret = fpga_open(device, &dev, speed);
	switch (ret) {
	case 0:
	    printf("open device success!\n");
	    break;
	case -1:
	    printf("bus error\n");
	    break;
	case -2:
	    printf("unknow device ID\n");
	    break;
	}
    }
}
void do_alive()
{
    int times   = 0;
    int success = 0;
    int ret;
    if (is_do_alive == 0) {
	return;
    }
    while (1) {
	times++;
	// fpga_alive(dev);
	switch (ret) {
	case 0:
	    success++;
	    printf("\rfpga alive");
	    break;
	default:
	    printf("\rbus error");
	    break;
	}
	printf(" %d/%d", success, times);
    }
}
// #include "spi_tr700.h"

void list_env()
{
    char val[PRE_ENV_LEN] = { 0 };
    char envs[][32]       = {
        { "sn" },
        { "ch1_10_adc" },
        { "ch1_10_dac" },
        { "ch2_10_adc" },
        { "ch2_10_dac" },
        { "ch3_10_adc" },
        { "ch3_10_dac" },
        { "ch1_5_adc" },
        { "ch1_5_dac" },
        { "ch2_5_adc" },
        { "ch2_5_dac" },
        { "ch3_5_adc" },
        { "ch3_5_dac" },
        { "lv1_low" },
        { "lv1_high" },
        { "lv2_low" },
        { "lv2_high" },
        { "lv3_low" },
        { "lv3_high" },
        { "lv4_low" },
        { "lv4_high" },
        { "lv5_low" },
        { "lv5_high" },
        { "lv6_low" },
        { "lv6_high" },
        { "lv7_low" },
        { "lv7_high" },
        { "ch1_wave" },
        { "ch2_wave" },
        { "ch3_wave" },
        { "ch1_en" },
        { "ch2_en" },
        { "ch3_en" },
        { "_1625_ref_1310" },
        { "_1550_ref_1310" },
        { "_980_ref_1310" },
        { "_850_ref_1310" },
        { "_1480_ref_1310" },
        { "_1490_ref_1310" },
    };

    for (int i = 0; i < ARRAY_SIZE(envs); i++) {
	stm_getenv(dev, envs[i], &val);
	printf("%12s:\t%s\n", envs[i], val);
    }
}

struct env_s
{
    char env[32];
    char val[32];
};
#include "any-chip.h"
void test_env()
{
    char         val[PRE_ENV_LEN] = { 0 };
    struct env_s envs[]           = {
        { "sn", "0123456789" },
        { "ch1_10_adc", "300]" },
        { "ch1_10_dac", "350]" },
        { "ch2_10_adc", "300]" },
        { "ch2_10_dac", "350]" },
        { "ch3_10_adc", "300]" },
        { "ch3_10_dac", "350]" },
        { "ch1_wave", "1310]" },
        { "ch2_wave", "1550]" },
        { "ch3_wave", "1490]" },
        { "ch1_en", "1]" },
        { "ch2_en", "1]" },
        { "ch3_en", "1]" },
    };
    struct env_s envs2[] = {
	{ "sn", "0123456789*" },
	{ "ch1_10_adc", "300*" },
	{ "ch1_10_dac", "350*" },
	{ "ch2_10_adc", "300*" },
	{ "ch2_10_dac", "350*" },
	{ "ch3_10_adc", "300*" },
	{ "ch3_10_dac", "350*" },
	{ "ch1_wave", "1310*" },
	{ "ch2_wave", "1550*" },
	{ "ch3_wave", "1490*" },
	{ "ch1_en", "1*" },
	{ "ch2_en", "1*" },
	{ "ch3_en", "1*" },
    };

    for (int i = 0; i < ARRAY_SIZE(envs); i++) {
	stm_setenv(dev, envs[i].env, envs[i].val);
    }
    unsigned long task_readkey;
    task_readkey = jiffies + 100;
    while (time_before(jiffies, task_readkey)) {
    }

    for (int i = 0; i < ARRAY_SIZE(envs); i++) {
	stm_getenv(dev, envs[i].env, &val);
	if (strcmp(val, envs[i].val) != 0) {
	    printf("error");
	}
	printf("%12s:\t%s\n", envs[i].env, val);
    }

    for (int i = 0; i < ARRAY_SIZE(envs2); i++) {
	stm_setenv(dev, envs2[i].env, envs2[i].val);
    }
    task_readkey = jiffies + 100;
    while (time_before(jiffies, task_readkey)) {
    }
    for (int i = 0; i < ARRAY_SIZE(envs2); i++) {
	stm_getenv(dev, envs2[i].env, &val);
	if (strcmp(val, envs2[i].val) != 0) {
	    printf("error");
	}
	printf("%12s:\t%s\n", envs2[i].env, val);
    }
}

void set_env()
{
    char         val[PRE_ENV_LEN] = { 0 };
    struct env_s envs[]           = {
        { "sn", "[0123456789]" },
        { "ch1_10_adc", "[300]" },
        { "ch1_10_dac", "[350]" },
        { "ch2_10_adc", "[300]" },
        { "ch2_10_dac", "[350]" },
        { "ch3_10_adc", "[300]" },
        { "ch3_10_dac", "[350]" },
        { "ch1_wave", "[1310]" },
        { "ch2_wave", "[1550]" },
        { "ch3_wave", "[1490]" },
        { "ch1_en", "[1]" },
        { "ch2_en", "[1]" },
        { "ch3_en", "[1]" },
    };
    struct env_s envs2[] = {
	{ "sn", "*0123456789*" },
	{ "ch1_10_adc", "*300*" },
	{ "ch1_10_dac", "*350*" },
	{ "ch2_10_adc", "*300*" },
	{ "ch2_10_dac", "*350*" },
	{ "ch3_10_adc", "*300*" },
	{ "ch3_10_dac", "*350*" },
	{ "ch1_wave", "*1310*" },
	{ "ch2_wave", "*1550*" },
	{ "ch3_wave", "*1490*" },
	{ "ch1_en", "*1*" },
	{ "ch2_en", "*1*" },
	{ "ch3_en", "*1*" },
    };

    for (int i = 0; i < ARRAY_SIZE(envs); i++) {
	stm_setenv(dev, envs[i].env, envs[i].val);
    }
}

void draw_title(const char *title)
{
    int i;

    printf("\r\n"), printf("\r\n");
    for (i = 0; i < 78; i++) {
	printf("*");
    }
    printf("\r\n");
    printf("\t%s\r\n", title);
    for (i = 0; i < 78; i++) {
	printf("*");
    }
    printf("\r\n");
}
int do_getenv()
{
    if (is_do_getenv == 0) {
	return 0;
    }
    draw_title(__FUNCTION__);

    if (strcmp(in_env, "all") == 0) {
	list_env();
    }
    else {
	char val[PRE_ENV_LEN] = "";
	if (-1 == stm_getenv(dev, in_env, &val)) {
	    return -1;
	}
	printf("%12s:\t%s\n", in_env, val);
    }
    return 0;
}

int do_setenv()
{
    if (is_do_setenv == 0) {
	return 0;
    }
    draw_title(__FUNCTION__);
    stm_setenv(dev, in_env, in_env_val);
}

int do_saveenv()
{
    if (is_do_saveenv == 0) {
	return 0;
    }
    draw_title(__FUNCTION__);
    stm_saveenv(dev);
}
extern void watch_ls(struct stm32_spi_dev *dev);
int         do_watch_ls()
{
    if (is_do_watch_ls == 0) {
	return 0;
    }
    watch_ls(dev);
    return 0;
}

extern void watch_opm(struct stm32_spi_dev *dev);
int         do_watch_opm()
{
    if (is_do_watch_opm == 0) {
	return 0;
    }
    struct tr700_getopm val;
    // stm_getopm(dev, &val);

    // printf("wave %d dbm %f mode %d\n", val.wave, val.dbm, val.mode);
    watch_opm(dev);
    return 0;
}
// int stm_getopm(struct stm32_spi_dev *dev, struct tr700_getopm *val);
int do_red()
{
    if (is_do_red == 0) {
	return 0;
    }

    printf("******** control red light ********\n");

    // fpga_red_laser(dev, red);
    test_env();
    list_env();
    return 0;
    // set_env();
    // list_env();
    for (int i = 0; i < 20; i++) {
	struct tr700_getopm val;
	stm_getopm(dev, &val);

	printf("wave %d dbm %f mode %d\n", val.wave, val.dbm, val.mode);
	sleep(1);
    }
    for (int i = 0; i < 1; i++) {
	// stm_setenv(dev, "sn","12---3");
	// stm_setenv(dev, "ch1_wave","4441");
	{
	    char val[PRE_ENV_LEN];

	    stm_getenv(dev, "ch1_wave", &val);
	    printf("val %s\n", val);
	    // sleep(1);
	    stm_getenv(dev, "sn", &val);
	    printf("val %s\n", val);
	}
	// stm_setenv(dev, "ch1_wave","1234");
	// {
	// 	char val[PRE_ENV_LEN];

	// 	stm_getenv(dev, "ch1_wave", &val);
	// 	printf("val %s\n", val);
	// }

	// usleep(1000000);

	{
	    struct tr700_setls_tx val1;
	    val1.ch   = LS_CH_1;
	    val1.mode = LS_MODE_CW;
	    val1.dbm  = -6.21;
	    stm_setls(dev, &val1);
	    usleep(1000000);
	}
	return 0;
	stm_saveenv(dev);
	usleep(1000000);
    }

    return 0;
}

#if CONFIG_MISC_TR700_STM32
#include "misc-tr700-stm32.h"
int do_test_misc()
{
    if (is_do_test == 0) {
	return 0;
    }
    struct dev_stm_info dsi;

    tr700_stm_open(&dsi);

    tr700_ls_on(&dsi, 1550, -3, LS_MODE_CW);
    tr700_ls_off(&dsi);

    float power_mW;
    float power_dBm;
    float power_ref;


    tr700_opm_read(&dsi, 1550, 0, &power_mW, &power_dBm, &power_ref);

    printf("power_mW    %2.2f\r\n", power_mW);
    printf("power_dBm   %2.2f\r\n", power_dBm);
    printf("power_dBm   %2.2f\r\n", power_dBm);


    tr700_opm_getref(&dsi, 1550, &power_dBm);

    printf("opm ref     %2.2f\r\n", power_dBm);
    tr700_stm_close(&dsi);
}
#endif  // End CONFIG_MISC_TR700

/**
 * @brief	值为了演示
 * 输入./stm32-spi-chip.elf  -t 可执行
 */
extern int stm_ls_wavelist(struct stm32_spi_dev *dev, struct wave_list *list, int count);

int do_test()
{
    if (is_do_test == 0) {
	return 0;
    }
    {
	printf(C_YELLOW "\r\n设备基本信息\r\n" C_NORMAL);

	char val[PRE_ENV_LEN] = { 0 };

	stm_getenv(dev, "sn", &val);
	printf("设备序列号 %s\r\n", val);

	printf(C_YELLOW "\r\n读取通道、波长信息，方法1：\r\n" C_NORMAL);
	stm_getenv(dev, "ch1_en", &val);
	if (atoi(val)) {
	    stm_getenv(dev, "ch1_wave", &val);
	    printf("通道1 波长 %d\r\n", atoi(val));
	}
	else {
	    printf("通道1 未焊接激光器\r\n");
	}

	stm_getenv(dev, "ch2_en", &val);
	if (atoi(val)) {
	    stm_getenv(dev, "ch2_wave", &val);
	    printf("通道2 波长 %d\r\n", atoi(val));
	}
	else {
	    printf("通道2 未焊接激光器\r\n");
	}

	stm_getenv(dev, "ch3_en", &val);
	if (atoi(val)) {
	    stm_getenv(dev, "ch3_wave", &val);
	    printf("通道3 波长 %d\r\n", atoi(val));
	}
	else {
	    printf("通道3 未焊接激光器\r\n");
	}


	struct wave_list list[3];

	printf(C_YELLOW "\r\n读取通道、波长信息，方法2：\r\n" C_NORMAL);
	stm_ls_wavelist(dev, list, 3);

	for (int i = 0; i < 3; i++) {
	    printf("通道%d 波长 %d\r\n", list[i].ch, list[i].wave);
	}
    }

    {
	printf(C_YELLOW "\r\n从波长查找通道\r\n" C_NORMAL);
	int ch;

	ch = stm_wave2ch(dev, 1310);
	if (ch) {
	    printf("1310 在通道 %d\r\n", ch);
	}
	else {
	    printf("不存在 1310 波长通道\r\n");
	}
	ch = stm_wave2ch(dev, 1550);
	if (ch) {
	    printf("1550 在通道 %d\r\n", ch);
	}
	else {
	    printf("不存在 1550 波长通道\r\n");
	}
	ch = stm_wave2ch(dev, 1490);
	if (ch) {
	    printf("1490 在通道 %d\r\n", ch);
	}
	else {
	    printf("不存在  1490 波长通道\r\n");
	}
    }
    {
	printf(C_YELLOW "\r\n从通道查找波长\r\n" C_NORMAL);
	int wave;

	wave = stm_ch2wave(dev, 1);
	if (wave) {
	    printf("通道1 关联波长 %d\r\n", wave);
	}
	else {
	    printf("通道1没激光器\r\n");
	}
	wave = stm_ch2wave(dev, 2);
	if (wave) {
	    printf("通道2 关联波长 %d\r\n", wave);
	}
	else {
	    printf("通道2没激光器\r\n");
	}
	wave = stm_ch2wave(dev, 3);
	if (wave) {
	    printf("通道3 关联波长 %d\r\n", wave);
	}
	else {
	    printf("通道 没激光器\r\n");
	}
    }
    {
	printf(C_YELLOW "\r\n光源测试\r\n" C_NORMAL);

	struct tr700_setls_tx val;

	printf("通道1输出 -8dBm\r\n");
	val.ch   = LS_CH_1;
	val.mode = LS_MODE_CW;
	val.dbm  = -8;
	stm_setls(dev, &val);
	sleep(2);

	printf("通道2输出 -8dBm\r\n");
	val.ch   = LS_CH_2;
	val.mode = LS_MODE_CW;
	val.dbm  = -8;
	stm_setls(dev, &val);
	sleep(2);

	printf("关闭光源\r\n");
	val.ch = LS_CH_OFF;
	stm_setls(dev, &val);
	sleep(1);
    }


    {
	printf(C_YELLOW "\r\n光功率计测试\r\n" C_NORMAL);
	// TODO 切换光功率计量程

	struct tr700_getopm val;
	printf("读取光功\r\n");
	for (int i = 0; i < 5; i++) {

	    stm_getopm(dev, &val);

	    printf("Wave %d dBm %2.2f Mode %d\n", val.wave, val.dbm, val.mode);
	    sleep(1);
	}
    }
}
int do_version()
{
    if (is_do_version == 0) {
	return 0;
    }
    char val[PRE_ENV_LEN] = { 0 };
    char envs[][32]       = {
        { "ver" },
        { "sn" },
    };

    for (int i = 0; i < ARRAY_SIZE(envs); i++) {
	stm_getenv(dev, envs[i], &val);
	printf("%12s:\t%s\n", envs[i], val);
    }
    return 0;
}
#if 0
void start_otdr(struct stm32_spi_dev *dev)
{
	struct fpga_test_param param;
	struct fpga_test_param _devparam;

	AUTO_BUILD_1KM(&param);
	_devparam.laser 	 = param.laser;
	_devparam.pulse 	 = param.pulse;
	_devparam.freq 	 	 = 0x90;  // param.freq ;
	_devparam.adopt_pt 	 = 8;  // param.adopt_pt / 4000;
	_devparam.add_cnt 	 = param.add_cnt;
	_devparam.power 	 = param.power;
	_devparam.amp 	 	 = param.amp;
	_devparam.apd_vol 	 = param.apd_vol;
	// _devparam.slot 	 	 = param.slot;
	// _devparam.ch 	 	 = param.ch;

	fpga_test(dev, OTDR_SETTING, (char *)&_devparam,
	          sizeof(struct fpga_test_param));
	fpga_test(dev, OTDR_START, NULL, 0);
}
#endif
// void start_otdr(struct stm32_spi_dev *dev)
// {
// 	struct fpga_test_param param;

// 	AUTO_BUILD_1KM(&param);
// 	// fpga_otdr_param(dev, &param);
// 	// fpga_test(dev, OTDR_START, NULL, 0 );
// }

#define DO_LONG 0
#define SWAP    1
int do_swap(unsigned char *buf, int len)
{
    return 0;
}


void save_file(unsigned long *pt, unsigned long len)
{
}

#include "signal.h"
#include <sys/time.h>
// unsigned int jiffies = 0;
void sigalrm_fn(int sig)
{
    // jiffies += 1;
    // printf("sdfsdf\n");
}


#include <termios.h>
#include <unistd.h>
static struct termios stored_settings;

void set_keypress(void)  // 设置终端为RAW模式，并关闭回显
{
    struct termios new_settings;
    tcgetattr(0, &stored_settings);
    new_settings = stored_settings;

    // new_settings.c_lflag &= (~ICANON);
    new_settings.c_lflag &= (~ECHO);
    new_settings.c_cc[VTIME] = 0;
    new_settings.c_cc[VMIN]  = 1;
    tcsetattr(0, TCSANOW, &new_settings);
    return;
}

void reset_keypress(void)  //恢复终端属性

{
    tcsetattr(0, TCSANOW, &stored_settings);
    return;
}

#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <termios.h>
#include <unistd.h>

int kbhit(void)
{
    fd_set         rfds;
    struct timeval tv;
    int            retval;

    /* Watch stdin (fd 0) to see when it has input. */
    FD_ZERO(&rfds);
    FD_SET(0, &rfds);
    /* Wait up to five seconds. */
    tv.tv_sec  = 0;
    tv.tv_usec = 0;

    retval = select(1, &rfds, NULL, NULL, &tv);
    /* Don't rely on the value of tv now! */

    if (retval == -1) {
	perror("select()");
	return 0;
    }
    else if (retval) {
	return 1;
    }
    else {
	/* FD_ISSET(0, &rfds) will be true. */
	return 0;
    }
    return 0;
}


int main(int argc, char *argv[])
{
    int ret = 0;

#if 0
	{
		signal(SIGALRM, sigalrm_fn);
		struct itimerval new_value, old_value;
		new_value.it_value.tv_sec = 0;
		new_value.it_value.tv_usec = 1;
		new_value.it_interval.tv_sec = 0;
		new_value.it_interval.tv_usec = 1000;
		// 改成1ms中断STM32立马崩溃，以后再处理
		setitimer(ITIMER_REAL, &new_value, &old_value);
		PRINTW("一个可以调试STM32 SPI的位置\n");
	}
#endif
    // jiffies = times(NULL);
    // unsigned long HZ = sysconf( _SC_CLK_TCK );
    // printf("jiffies %d %d\n", jiffies, HZ);
    // sleep(1);
    // jiffies = times(NULL);

    // printf("jiffies %d\n", jiffies);


    // fun();
    // 读取输入选项
    parse_opts(argc, argv);

    // 显示当前配置
    print_configure();

    ret = stm_open(device, &dev, speed);
    // stm_alive(dev);

    switch (ret) {
    case 0:
	printf("open device success!\n");
	break;
    case -1:
	printf("bus error\n");
	return -1;
    case -2:
	printf("unknow device ID\n");
	return -1;
    }
    // 没有任何输入参数需要检查
    // if (-1 == check_xxx()) {
    // 		return -1
    // }

    do_forever();
    do_alive();

    // 执行指令
    do_version();
    do_saveenv();
    do_getenv();
    do_setenv();
    do_watch_ls();
    do_watch_opm();
#if CONFIG_MISC_TR700_STM32
    do_test_misc();
#endif
    do_test();
    // do_red();

    stm_close(dev);
    return 0;
}

#ifdef PRJ_NAME
MODULE_PROJECT(PRJ_NAME);
#endif
#if defined(PRJ_VERSION) && defined(PRJ_PATCHLEVEL) && defined(PRJ_SUBLEVEL)
MODULE_VERSION(PRJ_VERSION "." PRJ_PATCHLEVEL "." PRJ_SUBLEVEL);
#endif

MODULE_BUILD(__DATE__ " " __TIME__);


MODULE_AUTHOR("MenglongWu <MenglongWoo@aliyun.com>");
MODULE_DESCRIPTION("otdr fpga-20c Ver.2015 test tool");
MODULE_DEPEND("spi_mxs.ko spidev.ko spi2dev.ko libstm32-spi");
PROG_GITSHA1(__GIT_SHA1__);
